package org.example.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.example.common.R;
import org.example.common.StatusCode;
import org.example.pojo.entity.SysMenu;
import org.example.pojo.entity.SysRoleMenu;
import org.example.pojo.entity.SysUserRole;
import org.example.pojo.req.MenuReq;
import org.example.pojo.vo.MenuVo;
import org.example.mapper.SysMenuMapper;
import org.example.service.SysMenuService;
import org.example.service.SysRoleMenuService;
import org.example.service.SysUserRoleService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author 妖妖零
 * @description 针对表【sys_menu(菜单权限表)】的数据库操作Service实现
 * @createDate 2024-05-06 20:44:43
 */
@Service
public class SysMenuServiceImpl extends ServiceImpl<SysMenuMapper, SysMenu>
        implements SysMenuService {


    @Autowired
    private SysUserRoleService sysUserRoleService;

    @Autowired
    private SysRoleMenuService sysRoleMenuService;

    /**
     * 构造菜单树
     *
     * @param menuName
     * @param status
     * @return
     */
    @Override
    public List<MenuVo> getList(String menuName, String status) {
        List<SysMenu> sysMenus = this.list();
        //构造菜单树
        List<MenuVo> menuVoList = new ArrayList<>();
        LambdaQueryWrapper<SysMenu> wrapper = new LambdaQueryWrapper();

        if (StringUtils.isNoneBlank(status) && StringUtils.isNotBlank(menuName)) {
            wrapper.like(SysMenu::getMenuName, menuName);
            wrapper.eq(SysMenu::getStatus, status);
            SysMenu sysMenu = this.getOne(wrapper);
            //构建菜单树
            listMenuTreeCondition(menuVoList, sysMenus, sysMenu);
            return menuVoList;
        }

        if (StringUtils.isNoneBlank(menuName)) {
            wrapper.like(SysMenu::getMenuName, menuName);
            SysMenu sysMenu = this.getOne(wrapper);
            //构建菜单树
            listMenuTreeCondition(menuVoList, sysMenus, sysMenu);
            return menuVoList;
        }
        if (StringUtils.isNoneBlank(status)) {
            wrapper.eq(SysMenu::getStatus, status);
            List<SysMenu> sysMenu = this.list(wrapper);
            //构建菜单树
            listMenuTree(menuVoList, sysMenu);
            return menuVoList;
        }

        //无条件查询默认显示所有
        List<MenuVo> menuVos = listMenuTree(menuVoList, sysMenus);
        return menuVos;
    }


    /**
     * 构造查询条件获取菜单树
     *
     * @param menuVoList
     * @param sysMenus
     */
    public static List<MenuVo> listMenuTree(List<MenuVo> menuVoList, List<SysMenu> sysMenus) {

        for (SysMenu sysMenu : sysMenus) {
            if (sysMenu.getParentId().toString().equals("0")) {
                MenuVo menuVo = new MenuVo();
                BeanUtils.copyProperties(sysMenu, menuVo);
                menuVo.setChildren(findChildren(sysMenus, sysMenu));
                menuVoList.add(menuVo);
            }
        }

        return menuVoList;
    }

    /**
     * 构造菜单树
     *
     * @param allMenus
     * @param sysMenu
     * @return
     */
    private static List<MenuVo> findChildren(List<SysMenu> allMenus, SysMenu sysMenu) {
        List<MenuVo> menuVos = new ArrayList<>();
        allMenus.forEach(item -> {
            if (item.getParentId().equals(sysMenu.getMenuId())) {
                MenuVo menuVo = new MenuVo();
                BeanUtils.copyProperties(item, menuVo);
                menuVo.setChildren(findChildren(allMenus, item));
                menuVos.add(menuVo);
            }
        });
        return menuVos;
    }

    /**
     * 带条件查询菜单树
     *
     * @param menuVoList
     * @param sysMenus
     * @param Menu
     */
    private void listMenuTreeCondition(List<MenuVo> menuVoList, List<SysMenu> sysMenus, SysMenu Menu) {

        for (SysMenu sysMenu : sysMenus) {
            if (sysMenu.getParentId().toString().equals("0") && sysMenu.getMenuName().equals(Menu.getMenuName())) {
                MenuVo menuVo = new MenuVo();
                BeanUtils.copyProperties(sysMenu, menuVo);
                menuVo.setChildren(findChildren(sysMenus, sysMenu));
                menuVoList.add(menuVo);
            }
        }
    }


    /**
     * 删除菜单
     *
     * @param id
     */
    @Override
    public R removeMenu(String id) {
        //查找是否是最后一级菜单
        LambdaQueryWrapper<SysMenu> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysMenu::getParentId, id);
        List<SysMenu> sysMenus = this.list(wrapper);
        if (!CollectionUtils.isEmpty(sysMenus)) {
            //不能删除菜单
            return R.error(StatusCode.MENU_EXIT_CHILDREN);
        }
        //删除菜单
        this.removeById(id);
        return R.ok("删除成功");
    }

    /**
     * 获取用户权限列表数据
     *
     * @param userId
     * @return
     */
    @Override
    public List<SysMenu> getUserAuthorMenu(Long userId, String userName) {
        if (userName.equals("admin")) {
            //管理员获取所有菜单数据
            return this.list();
        }
        List<Long> roleIds = getUserRoleIds(userId);
        //查询菜单列表数据
        LambdaQueryWrapper<SysRoleMenu> roleMenuWrapper = new LambdaQueryWrapper<>();
        roleMenuWrapper.in(SysRoleMenu::getRoleId, roleIds);
        List<SysRoleMenu> roleMenus = sysRoleMenuService.list(roleMenuWrapper);
        //提取菜单id
        List<Long> menuIds = roleMenus.stream().map(SysRoleMenu::getMenuId).collect(Collectors.toList());
        //查询菜单列表数据
        LambdaQueryWrapper<SysMenu> menuWrapper = new LambdaQueryWrapper<>();
        menuWrapper.in(SysMenu::getMenuId, menuIds);
        return this.list(menuWrapper);

    }

    /**
     * 获取角色id集合
     *
     * @param userId
     * @return
     */
    public List<Long> getUserRoleIds(Long userId) {
        //获取角色信息
        LambdaQueryWrapper<SysUserRole> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysUserRole::getUserId, userId);
        List<SysUserRole> sysUserRoleList = sysUserRoleService.list(wrapper);
        //获取角色集合
        List<Long> roleIds = sysUserRoleList.stream().map(SysUserRole::getRoleId).collect(Collectors.toList());
        return roleIds;
    }

    /**
     * 添加菜单
     *
     * @param menuReq
     */
    @Override
    public void addOrEditMenu(MenuReq menuReq) {
        SysMenu sysMenu = new SysMenu();
        if (StringUtils.isBlank(menuReq.getValue())) {
            //add
            BeanUtils.copyProperties(menuReq, sysMenu);
            sysMenu.setMenuName(menuReq.getLabel());
            this.save(sysMenu);
        } else {
            //添加子级
            BeanUtils.copyProperties(menuReq, sysMenu);
            sysMenu.setMenuName(menuReq.getLabel());
            sysMenu.setParentId(Long.valueOf(menuReq.getValue()));
            this.updateById(sysMenu);
        }
    }

    /**
     * 编辑菜单
     *
     * @param menuReq
     */
    @Override
    public void editMenuInfo(MenuReq menuReq) {
        //修改的是本条信息
        SysMenu sysMenu = new SysMenu();
        BeanUtils.copyProperties(menuReq, sysMenu);
        sysMenu.setMenuName(menuReq.getLabel());
        sysMenu.setMenuId(Long.valueOf(menuReq.getId()));
        this.updateById(sysMenu);
        //选择了上级菜单
        if (!menuReq.getId().equals(menuReq.getValue())) {
            //修改为父级菜单的子级
            SysMenu menu = this.getById(menuReq.getId());
            menu.setParentId(Long.valueOf(menuReq.getValue()));
            this.updateById(menu);
        }
    }
}




